//
// Modified by dfc on 2021-12-09.
//

#ifndef JI_SAMPLEDETECTOR_HPP
#define JI_SAMPLEDETECTOR_HPP
#include <string>
#include <opencv2/opencv.hpp>
#include <inference_engine.hpp>

#include "ji.h"
#include "ji_utils.h"
#include "WKTParser.h"
#include "Configuration.hpp"
#include <openvino/openvino.hpp>
#include "json.h"

/**
 * 本demo采用基于YOLOV5的目标检测模型来实现COCO数据集的目标检测
 * 为了方便，采用CPU推理，并基于openvino
 * SampleDetetctor类是完全可自定义的算法类，名字可以修改，在设计时注意与ji.cpp配合，能实现ji.cpp中相应的接口函数即可！！！
 */

#define STATUS int
using namespace std;
using namespace cv;
using namespace InferenceEngine;
#include <vector>
#include <string>


class SampleDetector
{

public:
    typedef struct
    {
        union{
        float prob;
    float confidence;

        };
        std::string name;
        cv::Rect rect;

    int class_id;

            Json::Value tojsonvalue()
    {
        static  std::vector<std::string>  namep_map={"electric_scooter","person","bicycle","others"};

        Json::Value _root;
        _root["x"] = rect.x;
        _root["y"] = rect.y;
        _root["height"] = rect.height;
        _root["confidence"] = confidence;
        _root["width"] = rect.width;
        _root["name"] = namep_map[class_id%4];

        return _root;
    };

    } Object; //结构化信息
   ~SampleDetector();

    SampleDetector();

    //初始化检测器资源，模型加载等操作
    STATUS Init(string xml_path,float cof_threshold,float nms_area_threshold, string classesFile);

    //去初始化检测器资源
    STATUS UnInit();

    //业务处理函数，输入分析图片，返回算法分析结果
    bool Process(const Mat &inFrame, const char *args, JiEvent &event);

    //更新配置参数
    bool UpdateConfig(const char *args);

    //获取算法分析后的图片
    bool GetOutFrame(JiImageInfo **out, unsigned int &outCount);
    std::string operator()(cv::Mat &input);
    ov::CompiledModel compiled_model;
private:
    cv::Mat mOutputFrame{0};    // 用于存储算法处理后的输出图像，根据ji.h的接口规范，接口实现需要负责释放该资源
    JiImageInfo mOutImage[1]; // 根据算法实际需求，确定输出图片数组大小,本demo每次仅分析处理一幅图
    unsigned int mOutCount = 1;//本demo每次仅分析处理一幅图
    char* jsonResult=nullptr ; // 用于存储算法处理后输出到JI_EVENT的json字符串，根据ji.h的接口规范，接口实现需要负责释放该资源
    Configuration mConfig;     //跟配置相关的类

public:
    static const int ERROR_BASE = 0x0100;
    static const int ERROR_INVALID_INPUT = 0x0101;
    static const int ERROR_INIT = 0x0102;
    static const int ERROR_PROCESS = 0x0103;

    static const int SUCCESS_PROCESS = 0x1001;
    static const int SUCCESS_INIT = 0x1002;

private:
    STATUS ProcessImage(Mat &inFrame, std::vector<Object> &result);
    void nms(vector<Object>& inputBoxes);
    vector<string> classes;
    float sigmoid(float x);
    vector<int> get_anchors(int net_grid);
    bool parse_yolov5(const Blob::Ptr &blob,int net_grid,float cof_threshold,
        vector<Object>& detected_objects, const float ratio_h, const float ratio_w);

    //存储初始化获得的可执行网络
    ExecutableNetwork _network;
    OutputsDataMap _outputinfo;
    string _input_name;
    //参数区
    string _xml_path;                             //OpenVINO模型xml文件路径
    float _cof_threshold;                //置信度阈值,计算方法是框置信度乘以物品种类置信度
    float _nms_area_threshold;  //nms最小重叠面积阈值

};

#endif //JI_SAMPLEDETECTOR_HPP
